
using SqlSugar;
using Newtonsoft.Json;
using HtERP.Data;

namespace HtERP.Services
{
    public class BackupScheduleService : IBackupScheduleService
    {
        private readonly ISqlSugarClient _db;
        private readonly IDbBackupService _dbBackupService;
        private readonly ILogger<BackupScheduleService> _logger;
        private readonly IFileUploadService _fileUploadService;
        private readonly IAuthService _authService;
        private readonly IConfigService _configService;

        // 从 IBackupSchedulerService 继承的成员变量
        private readonly object _lock = new object();
        private bool _isRunning = false;
        
        public BackupScheduleService(
            ISqlSugarClient db,
            IDbBackupService dbBackupService,
            ILogger<BackupScheduleService> logger,
            IFileUploadService fileUploadService,
            IAuthService authService,
            IConfigService configService)
        {
            _db = db;
            _dbBackupService = dbBackupService;
            _logger = logger;
            _fileUploadService = fileUploadService;
            _authService = authService;
            _configService = configService;
        }
        
        /// <summary>
        /// 获取所有备份计划
        /// </summary>
        public async Task<List<BackupSchedule>> GetAllSchedulesAsync()
        {
            var schedules = await _db.Queryable<BackupSchedule>().ToListAsync();
            
            // 解析JSON属性
            foreach (var schedule in schedules)
            {
                if (!string.IsNullOrEmpty(schedule.DbConfigJson))
                {
                    try
                    {
                        schedule.DbConfig = JsonConvert.DeserializeObject<DbConnectionConfig>(schedule.DbConfigJson);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "解析数据库配置失败: {ScheduleId}", schedule.Id);
                    }
                }
                
                if (!string.IsNullOrEmpty(schedule.ScheduledBackupTimesJson))
                {
                    try
                    {
                        schedule.ScheduledBackupTimes = JsonConvert.DeserializeObject<List<string>>(schedule.ScheduledBackupTimesJson);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "解析备份时间列表失败: {ScheduleId}", schedule.Id);
                    }
                }
            }
            
            return schedules;
        }
        
        /// <summary>
        /// 获取指定ID的备份计划
        /// </summary>
        /// <param name="id">计划ID</param>
        public async Task<BackupSchedule> GetScheduleByIdAsync(Guid id)
        {
            var schedule = await _db.Queryable<BackupSchedule>().FirstAsync(s => s.Id == id);
            
            if (schedule != null)
            {
                // 解析JSON属性
                if (!string.IsNullOrEmpty(schedule.DbConfigJson))
                {
                    try
                    {
                        schedule.DbConfig = JsonConvert.DeserializeObject<DbConnectionConfig>(schedule.DbConfigJson);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "解析数据库配置失败: {ScheduleId}", schedule.Id);
                    }
                }
                
                if (!string.IsNullOrEmpty(schedule.ScheduledBackupTimesJson))
                {
                    try
                    {
                        schedule.ScheduledBackupTimes = JsonConvert.DeserializeObject<List<string>>(schedule.ScheduledBackupTimesJson);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "解析备份时间列表失败: {ScheduleId}", schedule.Id);
                    }
                }
            }
            
            return schedule;
        }
        
        /// <summary>
        /// 创建新的备份计划
        /// </summary>
        /// <param name="schedule">备份计划对象</param>
        public async Task<Guid> CreateScheduleAsync(BackupSchedule schedule)
        {
            if (schedule.Id == Guid.Empty)
            {
                schedule.Id = Guid.NewGuid();
            }
            
            // 序列化JSON属性
            if (schedule.DbConfig != null)
            {
                schedule.DbConfigJson = JsonConvert.SerializeObject(schedule.DbConfig);
            }
            
            if (schedule.ScheduledBackupTimes != null)
            {
                schedule.ScheduledBackupTimesJson = JsonConvert.SerializeObject(schedule.ScheduledBackupTimes);
            }
            
            // 由于ID是Guid类型，使用ExecuteCommandAsync而不是ExecuteReturnSnowflakeIdAsync
            var result = await _db.Insertable(schedule).ExecuteCommandAsync();
            _logger.LogInformation("添加了新的备份计划: {ScheduleName}", schedule.Name);
            
            return schedule.Id;
        }
        
        /// <summary>
        /// 更新备份计划
        /// </summary>
        /// <param name="schedule">备份计划对象</param>
        public async Task<bool> UpdateScheduleAsync(BackupSchedule schedule)
        {
            // 序列化JSON属性
            if (schedule.DbConfig != null)
            {
                schedule.DbConfigJson = JsonConvert.SerializeObject(schedule.DbConfig);
            }
            
            if (schedule.ScheduledBackupTimes != null)
            {
                schedule.ScheduledBackupTimesJson = JsonConvert.SerializeObject(schedule.ScheduledBackupTimes);
            }
            
            var result = await _db.Updateable(schedule).ExecuteCommandAsync();
            _logger.LogInformation("更新了备份计划: {ScheduleName}", schedule.Name);
            
            return result > 0;
        }
        
        /// <summary>
        /// 删除备份计划
        /// </summary>
        /// <param name="id">计划ID</param>
        public async Task<bool> DeleteScheduleAsync(Guid id)
        {
            // 先获取计划，以便删除相关备份文件
            var schedule = await GetScheduleByIdAsync(id);
            if (schedule != null)
            {
                // 获取并删除相关备份历史和文件
                var historyItems = await _db.Queryable<BackupHistory>()
                    .Where(h => h.ScheduleId == id)
                    .ToListAsync();
                
                foreach (var item in historyItems)
                {
                    if (!string.IsNullOrEmpty(item.BackupFilePath) && File.Exists(item.BackupFilePath))
                    {
                        try
                        {
                            File.Delete(item.BackupFilePath);
                        }
                        catch (Exception ex)
                        {
                            _logger.LogWarning(ex, "删除备份文件失败: {FilePath}", item.BackupFilePath);
                        }
                    }
                }
                
                // 删除备份历史
                await _db.Deleteable<BackupHistory>().Where(h => h.ScheduleId == id).ExecuteCommandAsync();
            }
            
            // 删除备份计划
            var result = await _db.Deleteable<BackupSchedule>().Where(s => s.Id == id).ExecuteCommandAsync();
            _logger.LogInformation("删除了备份计划: {ScheduleId}", id);
            
            return result > 0;
        }
        
        /// <summary>
        /// 启用或禁用备份计划
        /// </summary>
        /// <param name="id">计划ID</param>
        /// <param name="enabled">是否启用</param>
        public async Task<bool> ToggleScheduleStatusAsync(Guid id, bool enabled)
        {
            var schedule = await GetScheduleByIdAsync(id);
            if (schedule != null)
            {
                schedule.Enabled = enabled;
                var result = await UpdateScheduleAsync(schedule);
                _logger.LogInformation("{Status}了备份计划: {ScheduleName}", 
                    schedule.Enabled ? "启用" : "禁用", schedule.Name);
                
                return result;
            }
            
            return false;
        }
        
        /// <summary>
        /// 立即执行备份计划
        /// </summary>
        /// <param name="scheduleId">计划ID</param>
        public async Task<bool> ExecuteScheduleNowAsync(Guid scheduleId)
        {
            var schedule = await GetScheduleByIdAsync(scheduleId);
            if (schedule == null)
            {
                _logger.LogWarning("备份计划不存在: {ScheduleId}", scheduleId);
                return false;
            }
            
            var historyItem = new BackupHistory
            {
                Id = Guid.NewGuid(),
                ScheduleId = schedule.Id,
                ScheduleName = schedule.Name,
                BackupTime = DateTime.Now,
                IsSuccess = false
            };
            
            try
            {
                // 确保备份目录存在
                if (!Directory.Exists(schedule.BackupDirectory))
                {
                    Directory.CreateDirectory(schedule.BackupDirectory);
                }
                
                // 生成备份文件名
                string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
                string backupFileName = $"{schedule.Name}_{timestamp}.bak";
                string backupFilePath = Path.Combine(schedule.BackupDirectory, backupFileName);
                
                // 执行备份
                try
                {
                    // 构建连接字符串
                    string connectionString = string.Empty;
                    if (!string.IsNullOrEmpty(schedule.DbConfig.SqliteFilePath))
                    {
                        connectionString = schedule.DbConfig.SqliteFilePath;
                    }
                    else
                    {
                        // 根据数据库类型构建连接字符串
                    switch (schedule.DbConfig.DatabaseType.ToLower())
                    {
                        case "mysql":
                            connectionString = $"server={schedule.DbConfig.Server};port={schedule.DbConfig.Port};database={schedule.DbConfig.DatabaseName};uid={schedule.DbConfig.Username};pwd={schedule.DbConfig.Password};";
                            break;
                        case "sqlserver":
                            connectionString = $"Server={schedule.DbConfig.Server},{schedule.DbConfig.Port};Database={schedule.DbConfig.DatabaseName};User Id={schedule.DbConfig.Username};Password={schedule.DbConfig.Password};";
                            break;
                        case "postgresql":
                            connectionString = $"Host={schedule.DbConfig.Server};Port={schedule.DbConfig.Port};Database={schedule.DbConfig.DatabaseName};Username={schedule.DbConfig.Username};Password={schedule.DbConfig.Password};";
                            break;
                        case "access":
                            connectionString = schedule.DbConfig.AccessFilePath;
                            break;
                        default:
                            connectionString = $"Data Source={Path.Combine(schedule.BackupDirectory, schedule.DbConfig.DatabaseName ?? "default.db")};";
                            break;
                    }
                    }
                    
                    // 执行备份
                    // 使用备份计划中的压缩设置
                    var backupResult = await _dbBackupService.BackupDatabaseAsync(schedule.DbConfig.DatabaseType, connectionString, backupFilePath, schedule.Compress);
                    
                    historyItem.IsSuccess = backupResult.Success;
                    historyItem.BackupFileName = backupFileName;
                    historyItem.BackupFilePath = backupResult.BackupFilePath;
                    historyItem.Message = backupResult.Message;
                    
                    if (backupResult.Success && File.Exists(backupResult.BackupFilePath))
                    {
                        var fileInfo = new FileInfo(backupResult.BackupFilePath);
                        historyItem.FileSize = fileInfo.Length;
                        
                        // 如果需要上传到服务器
                                if (schedule.UploadToServer && !string.IsNullOrEmpty(schedule.ServerUrl))
                                {
                                    try
                                    {
                                        // 设置服务器URL
                                        // 注意：假设FileUploadService已经配置了正确的API基础URL
                                        // 构建上传请求
                                        var uploadRequest = new UploadRequest
                                        {
                                            FileName = fileInfo.Name,
                                            FileSize = fileInfo.Length,
                                            FileType = Path.GetExtension(fileInfo.Name).TrimStart('.'),
                                            UploadTime = DateTime.Now,
                                            BackupScheduleName = schedule.Name,
                                            DatabaseName = schedule.DbConfig?.DatabaseName ?? "未知数据库",
                                            DatabaseType = schedule.DbConfig?.DatabaseType.ToString() ?? "未知类型",
                                            SourceMachine = Environment.MachineName,
                                            Description = $"Database backup for {schedule.DbConfig?.DatabaseName ?? "未知数据库"}"
                                        };


                                        // 检查服务器连接
                                        if (!await _fileUploadService.CheckServerConnectionAsync())
                                        {
                                            _logger.LogWarning("无法连接到服务器，跳过文件上传");
                                            historyItem.Message += "，但无法连接到服务器";
                                        }
                                        else
                                        {
                                            // 执行上传
                                            _logger.LogInformation("开始上传文件到服务器: {FileName}", fileInfo.Name);
                                            var uploadStatus = await _fileUploadService.UploadFileAsync(backupResult.BackupFilePath, uploadRequest);

                                            if (uploadStatus.Completed)
                                            {
                                                _logger.LogInformation("上传备份文件成功: {FileName}", backupFileName);
                                            }
                                            else
                                            {
                                                _logger.LogWarning("上传备份文件失败: {ErrorMessage}", uploadStatus.ErrorMessage ?? "未知错误");
                                                historyItem.Message += $"，但上传到服务器失败: {uploadStatus.ErrorMessage ?? "未知错误"}";
                                            }
                                        }
                                    }
                                    catch (Exception ex)
                            {
                                _logger.LogError(ex, "上传备份文件异常: {FileName}", backupFileName);
                                historyItem.Message += $"，上传异常: {ex.Message}";
                            }
                        }
                    }
                    
                    // 清理旧备份
                    if (schedule.AutoDeleteOlderThanDays > 0)
                    {
                        await CleanupOldBackupsAsync(schedule);
                    }
                    
                    return true;
                }
                catch (Exception backupEx)
                {
                    historyItem.IsSuccess = false;
                    historyItem.Message = backupEx.Message;
                    _logger.LogError(backupEx, "备份执行失败: {ScheduleName}", schedule.Name);
                    return false;
                }
            }
            catch (Exception ex)
            {
                historyItem.IsSuccess = false;
                historyItem.Message = ex.Message;
                _logger.LogError(ex, "执行备份失败: {ScheduleName}", schedule.Name);
                return false;
            }
            finally
            {
                // 保存备份历史
                await _db.Insertable(historyItem).ExecuteCommandAsync();
            }
        }
        
        /// <summary>
        /// 获取指定备份计划的最新成功备份记录
        /// </summary>
        /// <param name="scheduleId">计划ID</param>
        public async Task<BackupHistory> GetLatestSuccessBackupHistoryAsync(Guid scheduleId)
        {
            try
            {
                var latestBackup = await _db.Queryable<BackupHistory>()
                    .Where(h => h.ScheduleId == scheduleId && h.IsSuccess)
                    .OrderByDescending(h => h.BackupTime)
                    .FirstAsync();
                
                return latestBackup;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取最新备份历史失败: {ScheduleId}", scheduleId);
                return null;
            }
        }
        
        /// <summary>
        /// 清理旧备份文件
        /// </summary>
        private async Task CleanupOldBackupsAsync(BackupSchedule schedule)
        {
            try
            {
                if (!Directory.Exists(schedule.BackupDirectory))
                    return;
                
                DateTime cutoffDate = DateTime.Now.AddDays(-schedule.AutoDeleteOlderThanDays);
                
                var files = Directory.GetFiles(schedule.BackupDirectory, "*.bak", SearchOption.TopDirectoryOnly)
                    .Where(f => new FileInfo(f).LastWriteTime < cutoffDate)
                    .ToList();
                
                foreach (var file in files)
                {
                    try
                    {
                        File.Delete(file);
                        _logger.LogInformation("删除了旧备份文件: {FilePath}", file);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "删除旧备份文件失败: {FilePath}", file);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "清理旧备份失败: {ScheduleName}", schedule.Name);
            }
        }
        
        /// <summary>
        /// 获取备份历史记录列表
        /// </summary>
        public async Task<List<BackupHistory>> GetBackupHistoryAsync(Guid? scheduleId = null, DateTime? startDate = null, DateTime? endDate = null, bool successOnly = false)
        {
            try
            {
                var query = _db.Queryable<BackupHistory>();
                
                // 按计划ID筛选
                if (scheduleId.HasValue)
                {
                    query = query.Where(h => h.ScheduleId == scheduleId.Value);
                }
                
                // 按开始日期筛选
                if (startDate.HasValue)
                {
                    query = query.Where(h => h.BackupTime >= startDate.Value);
                }
                
                // 按结束日期筛选
                if (endDate.HasValue)
                {
                    // 包含结束日期当天的所有记录
                    query = query.Where(h => h.BackupTime <= endDate.Value.Date.AddDays(1));
                }
                
                // 只返回成功的记录
                if (successOnly)
                {
                    query = query.Where(h => h.IsSuccess);
                }
                
                // 按时间倒序排列，最新的记录在前
                return await query.OrderByDescending(h => h.BackupTime).ToListAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取备份历史记录失败");
                return new List<BackupHistory>();
            }
        }
        
        /// <summary>
        /// 删除备份历史记录
        /// </summary>
        public async Task<bool> DeleteBackupHistoryAsync(Guid historyId)
        {
            try
            {
                var historyItem = await _db.Queryable<BackupHistory>().FirstAsync(h => h.Id == historyId);
                if (historyItem == null)
                {
                    _logger.LogWarning("备份历史记录不存在: {HistoryId}", historyId);
                    return false;
                }
                
                // 先删除对应的备份文件（如果存在）
                if (!string.IsNullOrEmpty(historyItem.BackupFilePath) && File.Exists(historyItem.BackupFilePath))
                {
                    try
                    {
                        File.Delete(historyItem.BackupFilePath);
                        _logger.LogInformation("删除了备份文件: {FilePath}", historyItem.BackupFilePath);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "删除备份文件失败: {FilePath}", historyItem.BackupFilePath);
                        // 文件删除失败不应阻止记录删除
                    }
                }
                
                // 删除数据库记录
                var result = await _db.Deleteable<BackupHistory>().Where(h => h.Id == historyId).ExecuteCommandAsync();
                _logger.LogInformation("删除了备份历史记录: {HistoryId}", historyId);
                
                return result > 0;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "删除备份历史记录失败: {HistoryId}", historyId);
                return false;
            }
        }
        
        /// <summary>
        /// 批量删除备份历史记录
        /// </summary>
        public async Task<int> BatchDeleteBackupHistoryAsync(List<Guid> historyIds)
        {
            if (historyIds == null || historyIds.Count == 0)
            {
                return 0;
            }
            
            try
            {
                // 获取要删除的历史记录
                var historyItems = await _db.Queryable<BackupHistory>()
                    .Where(h => historyIds.Contains(h.Id))
                    .ToListAsync();
                
                // 先删除对应的备份文件
                foreach (var item in historyItems)
                {
                    if (!string.IsNullOrEmpty(item.BackupFilePath) && File.Exists(item.BackupFilePath))
                    {
                        try
                        {
                            File.Delete(item.BackupFilePath);
                            _logger.LogInformation("删除了备份文件: {FilePath}", item.BackupFilePath);
                        }
                        catch (Exception ex)
                        {
                            _logger.LogWarning(ex, "删除备份文件失败: {FilePath}", item.BackupFilePath);
                            // 文件删除失败不应阻止记录删除
                        }
                    }
                }
                
                // 批量删除数据库记录
                var result = await _db.Deleteable<BackupHistory>()
                    .Where(h => historyIds.Contains(h.Id))
                    .ExecuteCommandAsync();
                
                _logger.LogInformation("批量删除了 {Count} 条备份历史记录", result);
                
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量删除备份历史记录失败");
                return 0;
            }
        }
        
        /// <summary>
        /// 添加备份历史记录
        /// </summary>
        /// <param name="historyItem">备份历史记录</param>
        /// <returns>是否添加成功</returns>
        public async Task<bool> AddBackupHistoryAsync(BackupHistory historyItem)
        {
            try
            {
                if (historyItem == null)
                {
                    _logger.LogWarning("添加备份历史记录失败：记录对象为空");
                    return false;
                }
                
                // 确保Id已设置
                if (historyItem.Id == Guid.Empty)
                {
                    historyItem.Id = Guid.NewGuid();
                }
                
                // 插入数据库
                var result = await _db.Insertable(historyItem).ExecuteCommandAsync();
                
                if (result > 0)
                {
                    _logger.LogInformation("添加备份历史记录成功: {ScheduleName}, 状态: {Status}", 
                        historyItem.ScheduleName, historyItem.IsSuccess ? "成功" : "失败");
                    return true;
                }
                else
                {
                    _logger.LogWarning("添加备份历史记录失败: 数据库操作返回0行影响");
                    return false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "添加备份历史记录时发生异常");
                return false;
            }
        }

        #region 调度服务管理实现

        // 添加内存中的备份计划列表
        private readonly List<BackupSchedule> _inMemorySchedules = new List<BackupSchedule>();

        /// <summary>
        /// 获取服务是否正在运行
        /// </summary>
        public bool IsRunning => _isRunning;

        /// <summary>
        /// 启动调度服务 - 现在只记录日志并管理运行状态，定时器管理已移至BackupSchedulerHostedService
        /// </summary>
        public void Start()
        {
            lock (_lock)
            {
                if (!_isRunning)
                {
                    _isRunning = true;
                    _logger.LogInformation("备份调度服务已启动 - 定时器管理已移至BackupSchedulerHostedService");
                }
            }
        }

        /// <summary>
        /// 停止调度服务 - 现在只记录日志并管理运行状态，定时器管理已移至BackupSchedulerHostedService
        /// </summary>
        public void Stop()
        {
            lock (_lock)
            {
                if (_isRunning)
                {
                    _isRunning = false;
                    _logger.LogInformation("备份调度服务已停止 - 定时器管理已移至BackupSchedulerHostedService");
                }
            }
        }

        #endregion
    }
}